"""
模拟器配置对话框
用于添加和编辑模拟器
"""
import tkinter as tk
from tkinter import ttk, messagebox
from typing import Dict, Any, Optional
from gui.field_selector import FieldSelectorDialog


class SimulatorDialog:
    """模拟器配置对话框"""

    def __init__(self, parent, json_config: Dict[str, Any], simulator_data: Optional[Dict[str, Any]] = None):
        """
        Args:
            parent: 父窗口
            json_config: JSON配置对象（用于字段选择）
            simulator_data: 模拟器数据（编辑模式时提供，None表示添加模式）
        """
        self.parent = parent
        self.json_config = json_config
        self.simulator_data = simulator_data
        self.is_edit_mode = simulator_data is not None
        self.result = None

        # 创建对话框
        self.dialog = tk.Toplevel(parent)
        self.dialog.title("编辑模拟器" if self.is_edit_mode else "添加模拟器")
        self.dialog.geometry("550x650")
        self.dialog.transient(parent)
        self.dialog.grab_set()

        # 居中显示
        self._center_dialog()

        # 配置变量（不再需要name_var）
        self.type_var = tk.StringVar(value='time')
        self.enable_var = tk.BooleanVar(value=True)

        # 目标字段
        self.targets = []  # 存储已选字段列表或字典

        # 配置参数变量（根据类型动态创建）
        self.config_vars = {}

        self.setup_ui()

        # 如果是编辑模式，填充现有数据
        if self.is_edit_mode:
            self.load_simulator_data()

    def _center_dialog(self):
        """将对话框居中显示"""
        self.dialog.update_idletasks()
        width = self.dialog.winfo_width()
        height = self.dialog.winfo_height()
        x = (self.dialog.winfo_screenwidth() // 2) - (width // 2)
        y = (self.dialog.winfo_screenheight() // 2) - (height // 2)
        self.dialog.geometry(f'{width}x{height}+{x}+{y}')

    def setup_ui(self):
        """设置UI"""
        main_frame = ttk.Frame(self.dialog, padding=10)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 基本信息区域
        basic_frame = ttk.LabelFrame(main_frame, text="基本信息", padding=10)
        basic_frame.pack(fill=tk.X, pady=(0, 10))

        # 类型
        type_frame = ttk.Frame(basic_frame)
        type_frame.pack(fill=tk.X, pady=5)
        ttk.Label(type_frame, text="类型:", width=12).pack(side=tk.LEFT)
        type_combo = ttk.Combobox(type_frame, textvariable=self.type_var,
                                   values=['time', 'num', 'location'], state='readonly')
        type_combo.pack(side=tk.LEFT, fill=tk.X, expand=True)
        type_combo.bind('<<ComboboxSelected>>', self.on_type_changed)

        # 启用状态
        enable_frame = ttk.Frame(basic_frame)
        enable_frame.pack(fill=tk.X, pady=5)
        ttk.Checkbutton(enable_frame, text="启用模拟器", variable=self.enable_var).pack(side=tk.LEFT)

        # 配置参数区域（动态内容）
        self.config_frame = ttk.LabelFrame(main_frame, text="配置参数", padding=10)
        self.config_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        # 目标字段区域
        targets_frame = ttk.LabelFrame(main_frame, text="目标字段", padding=10)
        targets_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))

        # 目标字段列表
        list_frame = ttk.Frame(targets_frame)
        list_frame.pack(fill=tk.BOTH, expand=True)

        self.targets_listbox = tk.Listbox(list_frame, height=6)
        self.targets_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.targets_listbox.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.targets_listbox.configure(yscrollcommand=scrollbar.set)

        # 目标字段按钮
        target_btn_frame = ttk.Frame(targets_frame)
        target_btn_frame.pack(fill=tk.X, pady=(5, 0))

        ttk.Button(target_btn_frame, text="选择字段...", command=self.select_targets).pack(side=tk.LEFT, padx=(0, 5))
        ttk.Button(target_btn_frame, text="移除选中", command=self.remove_target).pack(side=tk.LEFT)

        # 按钮区域
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X)

        ttk.Button(button_frame, text="确定", command=self.confirm).pack(side=tk.RIGHT, padx=(5, 0))
        ttk.Button(button_frame, text="取消", command=self.cancel).pack(side=tk.RIGHT)

        # 初始化配置表单
        self.create_config_form('time')

    def on_type_changed(self, event=None):
        """类型改变时重新创建配置表单"""
        sim_type = self.type_var.get()
        self.create_config_form(sim_type)

    def create_config_form(self, sim_type: str):
        """根据类型创建配置表单"""
        # 清空现有配置
        for widget in self.config_frame.winfo_children():
            widget.destroy()
        self.config_vars.clear()

        if sim_type == 'time':
            self._create_time_config()
        elif sim_type == 'num':
            self._create_num_config()
        elif sim_type == 'location':
            self._create_location_config()

    def _create_time_config(self):
        """创建时间模拟器配置表单"""
        # 时间格式
        format_frame = ttk.Frame(self.config_frame)
        format_frame.pack(fill=tk.X, pady=5)
        ttk.Label(format_frame, text="时间格式:", width=12).pack(side=tk.LEFT)
        self.config_vars['format'] = tk.StringVar(value='yyMMddHHmmss')
        format_combo = ttk.Combobox(format_frame, textvariable=self.config_vars['format'],
                                     values=['yyMMddHHmmss', 'yyyy-MM-dd HH:mm:ss', 'timestamp_s', 'timestamp_ms'])
        format_combo.pack(side=tk.LEFT, fill=tk.X, expand=True)

        # 偏移
        offset_frame = ttk.Frame(self.config_frame)
        offset_frame.pack(fill=tk.X, pady=5)
        ttk.Label(offset_frame, text="偏移(秒):", width=12).pack(side=tk.LEFT)
        self.config_vars['offset'] = tk.StringVar(value='0')
        ttk.Entry(offset_frame, textvariable=self.config_vars['offset']).pack(side=tk.LEFT, fill=tk.X, expand=True)

    def _create_num_config(self):
        """创建数值模拟器配置表单"""
        # 模式
        mode_frame = ttk.Frame(self.config_frame)
        mode_frame.pack(fill=tk.X, pady=5)
        ttk.Label(mode_frame, text="模式:", width=12).pack(side=tk.LEFT)
        self.config_vars['mode'] = tk.StringVar(value='random')
        mode_combo = ttk.Combobox(mode_frame, textvariable=self.config_vars['mode'],
                                   values=['random', 'increment'], state='readonly')
        mode_combo.pack(side=tk.LEFT, fill=tk.X, expand=True)

        # 最小值
        min_frame = ttk.Frame(self.config_frame)
        min_frame.pack(fill=tk.X, pady=5)
        ttk.Label(min_frame, text="最小值:", width=12).pack(side=tk.LEFT)
        self.config_vars['min'] = tk.StringVar(value='0')
        ttk.Entry(min_frame, textvariable=self.config_vars['min']).pack(side=tk.LEFT, fill=tk.X, expand=True)

        # 最大值
        max_frame = ttk.Frame(self.config_frame)
        max_frame.pack(fill=tk.X, pady=5)
        ttk.Label(max_frame, text="最大值:", width=12).pack(side=tk.LEFT)
        self.config_vars['max'] = tk.StringVar(value='100')
        ttk.Entry(max_frame, textvariable=self.config_vars['max']).pack(side=tk.LEFT, fill=tk.X, expand=True)

        # 步长
        step_frame = ttk.Frame(self.config_frame)
        step_frame.pack(fill=tk.X, pady=5)
        ttk.Label(step_frame, text="步长:", width=12).pack(side=tk.LEFT)
        self.config_vars['step'] = tk.StringVar(value='1')
        ttk.Entry(step_frame, textvariable=self.config_vars['step']).pack(side=tk.LEFT, fill=tk.X, expand=True)

        # 输出格式
        output_frame = ttk.Frame(self.config_frame)
        output_frame.pack(fill=tk.X, pady=5)
        ttk.Label(output_frame, text="输出格式:", width=12).pack(side=tk.LEFT)
        self.config_vars['outputFormat'] = tk.StringVar(value='decimal')
        output_combo = ttk.Combobox(output_frame, textvariable=self.config_vars['outputFormat'],
                                      values=['decimal', 'hex'], state='readonly')
        output_combo.pack(side=tk.LEFT, fill=tk.X, expand=True)

    def _create_location_config(self):
        """创建经纬度模拟器配置表单"""
        # 纬度范围
        lat_frame = ttk.Frame(self.config_frame)
        lat_frame.pack(fill=tk.X, pady=5)
        ttk.Label(lat_frame, text="纬度范围:", width=12).pack(side=tk.LEFT)

        lat_min_frame = ttk.Frame(lat_frame)
        lat_min_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.config_vars['lat_min'] = tk.StringVar(value='30.0')
        ttk.Entry(lat_min_frame, textvariable=self.config_vars['lat_min'], width=10).pack(side=tk.LEFT)
        ttk.Label(lat_min_frame, text=" 至 ").pack(side=tk.LEFT)
        self.config_vars['lat_max'] = tk.StringVar(value='40.0')
        ttk.Entry(lat_min_frame, textvariable=self.config_vars['lat_max'], width=10).pack(side=tk.LEFT)

        # 经度范围
        lng_frame = ttk.Frame(self.config_frame)
        lng_frame.pack(fill=tk.X, pady=5)
        ttk.Label(lng_frame, text="经度范围:", width=12).pack(side=tk.LEFT)

        lng_min_frame = ttk.Frame(lng_frame)
        lng_min_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.config_vars['lng_min'] = tk.StringVar(value='120.0')
        ttk.Entry(lng_min_frame, textvariable=self.config_vars['lng_min'], width=10).pack(side=tk.LEFT)
        ttk.Label(lng_min_frame, text=" 至 ").pack(side=tk.LEFT)
        self.config_vars['lng_max'] = tk.StringVar(value='130.0')
        ttk.Entry(lng_min_frame, textvariable=self.config_vars['lng_max'], width=10).pack(side=tk.LEFT)

    def select_targets(self):
        """选择目标字段"""
        sim_type = self.type_var.get()

        # 根据类型选择不同的选择器模式
        if sim_type == 'location':
            mode = 'location'
        else:
            mode = 'single'

        selector = FieldSelectorDialog(self.dialog, self.json_config, mode=mode)
        result = selector.show()

        if result:
            self.targets = result
            self.update_targets_display()

    def update_targets_display(self):
        """更新目标字段显示"""
        self.targets_listbox.delete(0, tk.END)

        if isinstance(self.targets, list):
            for target in self.targets:
                self.targets_listbox.insert(tk.END, target)
        elif isinstance(self.targets, dict):
            for key, value in self.targets.items():
                self.targets_listbox.insert(tk.END, f"{key}: {value}")

    def remove_target(self):
        """移除选中的目标字段"""
        selection = self.targets_listbox.curselection()
        if selection:
            index = selection[0]
            if isinstance(self.targets, list):
                del self.targets[index]
            self.update_targets_display()

    def load_simulator_data(self):
        """加载模拟器数据（编辑模式）"""
        if not self.simulator_data:
            return

        # 加载基本信息（不再加载name）
        sim_type = self.simulator_data.get('type', 'time')
        self.type_var.set(sim_type)
        self.enable_var.set(self.simulator_data.get('enable', True))

        # 加载目标字段
        self.targets = self.simulator_data.get('targets', [])
        self.update_targets_display()

        # 重新创建配置表单
        self.create_config_form(sim_type)

        # 加载配置参数
        config = self.simulator_data.get('config', {})
        if sim_type == 'time':
            self.config_vars['format'].set(config.get('format', 'yyMMddHHmmss'))
            self.config_vars['offset'].set(str(config.get('offset', 0)))
        elif sim_type == 'num':
            self.config_vars['mode'].set(config.get('mode', 'random'))
            self.config_vars['min'].set(str(config.get('min', 0)))
            self.config_vars['max'].set(str(config.get('max', 100)))
            self.config_vars['step'].set(str(config.get('step', 1)))
            self.config_vars['outputFormat'].set(config.get('outputFormat', 'decimal'))
        elif sim_type == 'location':
            lat_range = config.get('lat_range', [30.0, 40.0])
            lng_range = config.get('lng_range', [120.0, 130.0])
            self.config_vars['lat_min'].set(str(lat_range[0]))
            self.config_vars['lat_max'].set(str(lat_range[1]))
            self.config_vars['lng_min'].set(str(lng_range[0]))
            self.config_vars['lng_max'].set(str(lng_range[1]))

    def collect_config(self) -> Dict[str, Any]:
        """收集配置参数"""
        sim_type = self.type_var.get()
        config = {}

        try:
            if sim_type == 'time':
                config['format'] = self.config_vars['format'].get()
                config['offset'] = int(self.config_vars['offset'].get())
            elif sim_type == 'num':
                config['mode'] = self.config_vars['mode'].get()
                config['min'] = int(self.config_vars['min'].get())
                config['max'] = int(self.config_vars['max'].get())
                config['step'] = int(self.config_vars['step'].get())
                config['outputFormat'] = self.config_vars['outputFormat'].get()
            elif sim_type == 'location':
                lat_min = float(self.config_vars['lat_min'].get())
                lat_max = float(self.config_vars['lat_max'].get())
                lng_min = float(self.config_vars['lng_min'].get())
                lng_max = float(self.config_vars['lng_max'].get())
                config['lat_range'] = [lat_min, lat_max]
                config['lng_range'] = [lng_min, lng_max]
        except ValueError as e:
            raise ValueError(f"配置参数格式错误: {str(e)}")

        return config

    def confirm(self):
        """确认"""
        # 验证输入
        if not self.targets:
            messagebox.showwarning("提示", "请至少选择一个目标字段")
            return

        try:
            config = self.collect_config()
        except ValueError as e:
            messagebox.showerror("配置错误", str(e))
            return

        # 构建结果（不包含name字段）
        self.result = {
            'type': self.type_var.get(),
            'enable': self.enable_var.get(),
            'config': config,
            'targets': self.targets
        }

        self.dialog.destroy()

    def cancel(self):
        """取消"""
        self.result = None
        self.dialog.destroy()

    def show(self) -> Optional[Dict[str, Any]]:
        """显示对话框并返回结果"""
        self.dialog.wait_window()
        return self.result
